package com.small.nacos.naming.misc;

import com.alibaba.nacos.common.constant.HttpHeaderConsts;
import com.alibaba.nacos.common.http.HttpClientConfig;
import com.alibaba.nacos.common.http.client.NacosRestTemplate;
import com.alibaba.nacos.common.http.param.Header;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.nacos.common.http.param.Query;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.IoUtils;
import com.alibaba.nacos.common.utils.VersionUtils;
import com.small.nacos.sys.env.EnvUtil;
import org.apache.commons.codec.Charsets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

/**
 * @Author zhoujin
 * @Date 2022/11/1 9:34
 */
public class HttpClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClient.class);

    private static final NacosRestTemplate APACHE_SYNC_NACOS_REST_TEMPLATE = HttpClientManager.getApacheRestTemplate();

    public static RestResult<String> request(String url, HttpServletRequest req, int connectTimeout, int readTimeout, String encoding) throws IOException {
        List<String> headerList = new ArrayList<>(16);
        Enumeration<String> headers = req.getHeaderNames();
        while (headers.hasMoreElements()) {
            String headerName = headers.nextElement();
            headerList.add(headerName);
            headerList.add(req.getHeader(headerName));
        }

        final String body = IoUtils.toString(req.getInputStream(), Charsets.UTF_8.name());
        final Map<String, String> paramsValue = translateParameterMap(req.getParameterMap());

        return request(url, headerList, paramsValue, body,
                connectTimeout, readTimeout, encoding, req.getMethod());
    }


    public static RestResult<String> request(String url, List<String> headers, Map<String, String> paramValues,
                                             String body, int connectTimeout, int readTimeout, String encoding, String method) {
        Header header = Header.newInstance();
        if (CollectionUtils.isNotEmpty(headers)) {
            header.addAll(headers);
        }
        header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        header.addParam(HttpHeaderConsts.CLIENT_VERSION_HEADER, VersionUtils.version);
        header.addParam(HttpHeaderConsts.REQUEST_SOURCE_HEADER, EnvUtil.getLocalAddress());
        header.addParam(HttpHeaderConsts.ACCEPT_CHARSET, encoding);

        HttpClientConfig httpClientConfig = HttpClientConfig.builder().setConTimeOutMillis(connectTimeout)
                .setReadTimeOutMillis(readTimeout).build();
        Query query = Query.newInstance().initParams(paramValues);
        query.addParam("encoding", "UTF-8");
        try {
            return APACHE_SYNC_NACOS_REST_TEMPLATE
                    .exchange(url, httpClientConfig, header, query, body, method, String.class);
        } catch (Exception e) {
            LOGGER.warn("Exception while request: {}, caused: {}", url, e);
            return RestResult.<String>builder().withCode(500).withMsg(e.toString()).build();
        }
    }

    public static Map<String, String> translateParameterMap(Map<String, String[]> parameterMap) {

        Map<String, String> map = new HashMap<>(16);
        for (String key : parameterMap.keySet()) {
            map.put(key, parameterMap.get(key)[0]);
        }
        return map;
    }
}
